home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 25
/
Cream of the Crop 25.iso
/
faq
/
wdj0597.zip
/
ROBBINS.ZIP
/
DEFMAKER.CPP
next >
Wrap
C/C++ Source or Header
|
1997-03-10
|
8KB
|
231 lines
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "PEImage.h"
// The usage message.
void ShowUsage ( void ) ;
static char szSTDCallProblem[] =
"A non-decorated function call is exported. Unfortunately, there "
"is no way to turn a _stdcall function export into something in "
"the .DEF file without knowing the complete byte parameter count. "
"If you know for sure that the function in the title bar is _cdecl,"
" then you can press OK now. Otherwise, press CANCEL to save "
"yourself some grief." ;
int main ( int argc , char * argv[] )
{
printf ( "DEFMaker - The exports to .DEF file maker - "
"John Robbins 1997\n" ) ;
if ( 1 == argc )
{
ShowUsage ( ) ;
return ( 1 ) ;
}
// See if the input file exists.
WIN32_FIND_DATA stWFD ;
HANDLE hFind = FindFirstFile ( argv[ 1 ] , &stWFD ) ;
if ( INVALID_HANDLE_VALUE == hFind )
{
printf ( "%s does not exist\n" , argv[ 1 ] ) ;
return ( 1 ) ;
}
FindClose ( hFind ) ;
char szFile[ MAX_PATH ] ;
_splitpath ( argv[ 1 ] , NULL , NULL , szFile , NULL ) ;
// Now figure out the name of the output file.
char szOutput[ MAX_PATH ] ;
if ( 2 == argc )
{
strcpy ( szOutput , szFile ) ;
strcat ( szOutput , ".def" ) ;
}
else
{
strcpy ( szOutput , argv [ 2 ] ) ;
}
// Try and open the output file.
FILE * fileOut = fopen ( szOutput , "wt" ) ;
if ( NULL == fileOut )
{
printf ( "Unable to open %s\n" , szOutput ) ;
return ( 1 ) ;
}
// Stick all of the header information into the .DEF file.
fprintf ( fileOut , "; DEFMaker Generated .DEF file\n\n" ) ;
fprintf ( fileOut , "LIBRARY %s\n\n" , szFile ) ;
fprintf ( fileOut , "EXPORTS\n" ) ;
// We are ready to roll. Everything is put in a try catch block
// to make it easier to control resource cleanup.
// The error buffer
char szErrBuff[ 150 ] ;
try
{
// The PE File object.
CPEImage cPE ;
// Try and open the file.
PEI_ERROR pErr = cPE.LoadImage ( argv[ 1 ] ) ;
if ( PEI_NOERROR != pErr )
{
sprintf ( szErrBuff , "Unable to open %s\n" , argv[1] );
throw szErrBuff ;
}
// Now that we have it open, get the exports data.
DWORD dwExportsRVA =
cPE.
GetDataDirectoryRVA(IMAGE_DIRECTORY_ENTRY_EXPORT);
if ( NULL == dwExportsRVA )
{
sprintf ( szErrBuff , "%s has no exports!\n" , argv[1]);
throw szErrBuff ;
}
// Get the pointer to the exports directory.
PIMAGE_EXPORT_DIRECTORY pExpDir = (PIMAGE_EXPORT_DIRECTORY)
cPE.ImageRvaToFileVa(dwExportsRVA);
// Before we do anything else we check that the number of
// functions matches the number of exports. If they do
// not, then somewhere in the file are NONAME exports.
if ( pExpDir->NumberOfFunctions != pExpDir->NumberOfNames )
{
sprintf ( szErrBuff ,
"The number of exports and number of "
"names do not match. There is a NONAME "
"export in %s.\n" ,
argv[ 1 ] );
throw szErrBuff ;
}
// Get the pointer to the function address array.
PDWORD pdwAddr = (PDWORD)
cPE.ImageRvaToFileVa((DWORD)pExpDir->
AddressOfFunctions);
// Get the pointer to the function address array.
PWORD pwOrdinal = (PWORD)
cPE.ImageRvaToFileVa((DWORD)pExpDir->
AddressOfNameOrdinals);
// Get the address to the names array.
LPSTR *pszName = (PSTR *)
cPE.ImageRvaToFileVa((DWORD)pExpDir->
AddressOfNames);
// The current name we are looking at.
LPSTR szExpName ;
// The buffer where undecorated names are stored.
char szUnDec [ 1024 ] ;
// If there is an undecorated function, and the user has
// already indicated that they want to continue, don't keep
// prompting them.
BOOL bContinueAnyway = FALSE ;
for ( DWORD i = 0 ; i < pExpDir->NumberOfFunctions ; i++ )
{
// If this is just a gap in the exports, skip over it.
if ( 0 == pdwAddr [ i ] )
{
continue ;
}
szExpName = NULL ;
// Get the name address
szExpName =
(LPSTR)cPE.ImageRvaToFileVa((DWORD)pszName[i]);
// If the first character is NOT a question mark,
// we have a problem. However, if the user has
// already indicated that they want
if ( ( '?' != *szExpName ) &&
( FALSE == bContinueAnyway ) )
{
// Could it be a __stdcall export or __fastcall done
// through __declspec(dllexport) or put in the .DEF
// file that way?
if ( ( ( '_' != *szExpName ) ||
( '@' != *szExpName ) )&&
( NULL == strrchr ( szExpName + 1 , '@' ) ) )
{
// OK, pop up the message box.
if ( IDOK ==
MessageBox ( GetActiveWindow ( ) ,
szSTDCallProblem ,
szExpName ,
MB_OKCANCEL |
MB_ICONWARNING ) )
{
bContinueAnyway = TRUE ;
}
else
{
throw "User ended operation." ;
}
}
}
// If this is a name that can be undecorated, we will
// show it in a comment in the output file.
if ( 0 !=
UnDecorateSymbolName( szExpName ,
szUnDec ,
sizeof ( szUnDec ) ,
UNDNAME_NO_MS_KEYWORDS ) )
{
fprintf ( fileOut , "; %s\n" , szUnDec ) ;
}
// Notice that we are adding the starting base to the
// output ordinal. We don't want to get this out of
// whack.
fprintf ( fileOut ,
" %s @%d NONAME\n\n" ,
szExpName ,
pwOrdinal[ i ] + pExpDir->Base ) ;
// Do a little visual clue.
putchar ( '.' ) ;
}
}
catch ( char * szError )
{
printf ( "\n%s\n" , szError ) ;
// Close the output file.
fclose ( fileOut ) ;
// Don't leave any half backed files around.
DeleteFile ( szOutput ) ;
return ( 1 ) ;
}
// Close the output file.
fclose ( fileOut ) ;
return ( 0 ) ;
}
// Shows the usage message.
void ShowUsage ( void )
{
printf (
"Usage : DEFMaker <input dll> [output file]\n\n"
" <input dll> - The DLL with exports. Specify the complete \n"
" filename to the DLL.\n"
" [output file] - The optional output file. If not specified,\n"
" the output is the input filename with .DEF for\n"
" the extension. The output file is ALWAYS placed\n"
" in the current directory if not explicitly\n"
" set.\n\n"
) ;
}